Dyr og Data

Data Dashboards

Gavin Simpson

Aarhus University

Mona Larsen

Aarhus University

2025-11-18

Data dashboards

Overview

  • What is a dashboard?
  • Why use Quarto dashboards in R?
  • Key dashboard components used in the penguin example

What is a Quarto Dashboard?

  • A Quarto document rendered as a Reveal.js presentation
  • Designed for interactive data exploration and teaching
  • Supports: plots, tables, filters, value boxes, tabs, sidebars, and interactive widgets
  • Works with R, Python, and Observable JavaScript

Example dashboard

Dashboard YAML Structure

format:
  dashboard:
    theme: cosmo
    orientation: rows
    sidebar: true

Key options:

  • theme: visual style (e.g., cosmo, minty)
  • orientation: layout direction (rows or columns)
  • sidebar: whether a sidebar appears

Packages Used (R)

library("palmerpenguins")
library("tidyverse")
library("plotly")
  • palmerpenguins: sample dataset
  • tidyverse: data manipulation + plotting
  • plotly: interactive graphics

Value Boxes — Purpose

  • Display metric summaries prominently so users see important numbers at a glance.

Example (in a dashboard block):

::: {.value-box}
**Species Count**

```{r}
sum_stats$species_n
```
:::

Inputs / Filters

  • Use selectInput() (from shiny) or Quarto widgets to accept user choices.
selectInput(
  "species", 
  "Species",
  choices = unique(penguins$species)
)
selectInput(
  "var",
  "Variable",
  choices = c("bill_length_mm", "bill_depth_mm", "flipper_length_mm", "body_mass_g")
)

Reactive Data Filtering

filtered <- reactive({
  penguins |> filter(species == input$species)
})
  • Reactives automatically update downstream outputs (plots, tables)

  • note filtered is a function

Summary Table

filtered() |>
  group_by(island) |>
  summarise(across(where(is.numeric), mean, na.rm = TRUE))
  • Tables update automatically with the selected filters

Interactive Plot Example

plot_reactive <- reactive({
  ggplot(filtered(), aes_string(x = "bill_length_mm", y = input$var, color = "island")) +
    geom_point() + theme_minimal()
})

plotly::ggplotly(plot_reactive())
  • Plotly adds hover, zoom and pan to ggplot objects
  • note plot_reactive() is a function

Layout Tips

  • Keep controls (filters) separate from content (plots/tables) — use a sidebar.
  • Start with high-level summaries (value boxes) and allow drill-down with filters.
  • Use tabs or multiple rows for different analysis steps.

Row-Oriented Layout

+------------------------------------------------------+
| Row 1 (Stats)                                        |
+------------------------------------------------------+
| Row 2 (Plot Area)                                    |
+------------------------------------------------------+
| Row 3 (Data Table)                                   |
+------------------------------------------------------+

Visual Diagram: Column-Oriented Layout

+---------------------+-------------------------------+
| Column 1            | Column 2                      |
| (Filters/Sidebar)   | (Plots / Tables)              |
+---------------------+-------------------------------+
  • Row layouts are best for storytelling (summary → detail)
  • Columns are ideal for comparisons or separating controls

Dashboard Layout Basics

  • Dashboards are arranged in rows or columns
  • Each row/column can contain:
  • Plots
  • Tables
  • Value boxes
  • Text or explanation blocks
  • Use orientation: in YAML to switch between row‑based or column‑based layout
format:
  html:
    dashboard:
    orientation: rows # or 'columns'

Rows, Columns & Areas

Rows

  • Good for wide plots or tables
  • Natural flow for summary → details

Columns

  • Useful for side‑by‑side comparisons
  • Great for grouping related visuals

Row orientation

---
title: "Palmer Penguins"
author: "Cobblepot Analytics"
format: dashboard
---
    
## Row {height=70%}

```{r}
```

## Row {height=30%}

```{r}
```

```{r}
```

Column orientation

---
title: "Diamonds Explorer"
format: 
  dashboard:
    orientation: columns
---
    
## Column {width=60%}

```{r}
```

## Column {width=40%}

```{r}
```

```{r}
```

Example

## Row 1

::: {.value-box}
**Species Count**

```{r}
sum_stats$species_n
```
:::

## Row 2

```{r}
#| label: a-plot
penguins |> ggplot(...)
```

```{r}
#| label: a-table
penguins |> filter(species == "Adelie") |> knitr::kable()
```

Inline sidebard


---
title: "Palmer Penguins"
format: dashboard
server: shiny
---

## Row

### {.sidebar}

```{r}
```

### Column

```{r}
```

## Row

```{r}
```